package com.ruoyi.common.customize.util;

import com.ruoyi.common.base.user.domain.User;
import com.ruoyi.common.base.user.vo.UserToken;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.customize.constants.CommonFieldNameConstants;
import com.ruoyi.common.customize.enums.CommonDictEnum;
import com.ruoyi.common.customize.util.id.IdWorker;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 项目常用工具类
 *
 * @author gdk
 * @since 2021/11/14 5:22 下午
 */
@Component
@AllArgsConstructor
public class CommonUtil {
    /**
     * id属性名
     */
    public static final String ID = "id";
    /**
     * 创建人名称属性名
     */
    public static final String CREATE_NAME = "createName";
    /**
     * 修改人名称属性名
     */
    public static final String UPDATE_NAME = "updateName";
    /**
     * 状态属性名
     */
    public static final String STATUS = "status";
    /**
     * 是否删除属性名
     */
    public static final String IS_DELETE = "isDeleted";

    // ----------------------------------------------

    private final IdWorker idWorker;

    /**
     * 获得雪花id
     *
     * @return java.lang.Long
     * @author gdk
     * @since 2021/11/22
     * @since 1.0.0
     */
    public Long getId() {
        return idWorker.nextId();
    }

    /**
     * 抛出异常
     *
     * @author gdk
     * @since 2021/11/20
     * @since 1.0.0
     */
    public static void throwError() {
        throw new ServiceException();
    }

    /**
     * 判断当前是否有登录用户
     *
     * @return {@link boolean}
     * @author gdk
     * @since 2022/8/22 21:09
     */
    public static boolean hasLoginUser() {
        return SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof LoginUser;
    }

    /**
     * 获取当前用户
     *
     * @return {@link User}
     * @author gdk
     * @since 2021/11/20
     * @since 1.0.0
     */
    public static LoginUser getLoginUser() {
        if (hasLoginUser()) {
            return SecurityUtils.getLoginUser();
        }

        return null;
    }

    /**
     * 获取当前用户
     *
     * @return {@link User}
     * @author gdk
     * @since 2021/11/20
     * @since 1.0.0
     */
    public static LoginUser getLoginUserNotNull() {
        if (!hasLoginUser()) {
            throw new ServiceException("未能获取到用户信息");
        }

        return SecurityUtils.getLoginUser();
    }


    /**
     * 获取当前系统用户
     *
     * @return com.ruoyi.common.core.domain.entity.SysUser
     * @author gdk
     * @since 2021/11/20
     * @since 1.0.0
     */
    public static SysUser getSysUser() {
        LoginUser loginUser = getLoginUser();
        if (Objects.isNull(loginUser)) {
            return null;
        }

        return loginUser.getSysUser();
    }

    /**
     * 获取当前用户
     *
     * @return com.ruoyi.common.core.domain.entity.SysUser
     * @author gdk
     * @since 2021/11/20
     * @since 1.0.0
     */
    public static SysUser getSysUserNotNull() {
        LoginUser loginUser = getLoginUserNotNull();
        return loginUser.getSysUser();
    }

    /**
     * 获取当前用户id
     *
     * @return {@link Long}
     * @author gdk
     * @since 2023/5/16 16:56
     */
    public static Long getUserIdNotNull() {
        return getLoginUserNotNull().getUserId();
    }

    /**
     * 获取当前用户id
     *
     * @return {@link String}
     * @author gdk
     * @since 2023/5/16 16:56
     */
    public static String getStrUserIdNotNull() {
        return getUserIdNotNull().toString();
    }

    /**
     * 获取当前用户
     *
     * @return {@link User}
     * @author gdk
     * @since 2021/11/20
     * @since 1.0.0
     */
    public static UserToken getUser() {
        LoginUser loginUser = getLoginUser();
        if (Objects.isNull(loginUser)) {
            return null;
        }

        return loginUser.getUser();
    }

    /**
     * 获取当前用户
     *
     * @return {@link User}
     * @author gdk
     * @since 2021/11/20
     * @since 1.0.0
     */
    public static UserToken getUserNotNull() {
        LoginUser loginUser = getLoginUserNotNull();
        return loginUser.getUser();
    }

    /**
     * 初始化创建时数据
     *
     * @param parameter 对象
     * @author gdk
     * @since 2022/8/14 16:36
     */
    public void initCreateAbout(Object parameter) {
        initValue(parameter, CommonFieldNameConstants.INSERT_ABOUT_FIELD);
    }

    /**
     * 初始化创建时数据
     *
     * @param user      当前用户
     * @param now       当前时间
     * @param parameter 对象
     * @author gdk
     * @since 2022/8/14 16:36
     */
    public void initCreateAbout(Object parameter, LoginUser user, Date now) {
        initValue(parameter, CommonFieldNameConstants.INSERT_ABOUT_FIELD, user, now);
    }

    /**
     * 初始化修改时数据
     *
     * @param parameter 对象
     * @author gdk
     * @since 2022/8/14 16:36
     */
    public void initUpdateAbout(Object parameter) {
        initValue(parameter, CommonFieldNameConstants.UPDATE_ABOUT_FIELD);
    }

    /**
     * 初始化修改时数据
     *
     * @param parameter 对象
     * @param user      当前用户
     * @param now       当前时间
     * @author gdk
     * @since 2022/8/14 16:36
     */
    public void initUpdateAbout(Object parameter, LoginUser user, Date now) {
        initValue(parameter, CommonFieldNameConstants.UPDATE_ABOUT_FIELD, user, now);
    }

    /**
     * 初始化数据
     *
     * @param parameter     对象
     * @param needInitField 需要初始化的数据
     * @author gdk
     * @since 2022/8/14 16:36
     */
    public void initValue(Object parameter, List<String> needInitField) {
        LoginUser user = getLoginUser();
        Date now = new Date();
        initValue(parameter, needInitField, user, now);
    }

    /**
     * 初始化数据
     *
     * @param parameter     对象
     * @param needInitField 需要初始化的数据
     * @param user          当前用户
     * @param now           当前时间
     * @author gdk
     * @since 2022/8/14 16:36
     */
    public void initValue(Object parameter, List<String> needInitField, LoginUser user, Date now) {
        Field[] fields = ReflectUtil.getFiledAsList(parameter.getClass()).toArray(new Field[0]);

        try {
            // 遍历
            for (Field field : fields) {
                boolean contains = needInitField.contains(field.getName());
                if (!contains) {
                    continue;
                }

                if (!CommonFieldNameConstants.UPDATE_ABOUT_FIELD.contains(field.getName()) && !needFill(field, parameter)) {
                    continue;
                }

                // 打破封装
                field.setAccessible(true);
                // 如果有值，不处理
                if (!Objects.isNull(field.get(parameter))) {
                    field.setAccessible(false);
                    continue;
                }

                // 根据属性名设置对应的值
                switch (field.getName()) {
                    case CommonFieldNameConstants.ID:
                        field.set(parameter, getId());
                        break;

                    case CommonFieldNameConstants.CREATE_BY:
                    case CommonFieldNameConstants.UPDATE_BY:
                        if (!Objects.isNull(user)) {
                            if (field.getType().equals(String.class)) {
                                field.set(parameter, user.getUserId().toString());
                            } else if (field.getType().equals(Long.class)) {
                                field.set(parameter, user.getUserId());
                            }
                        }

                        break;

                    case CommonFieldNameConstants.CREATE_TIME:
                    case CommonFieldNameConstants.UPDATE_TIME:
                        if (!Objects.isNull(now)) {
                            field.set(parameter, now);
                        }
                        break;

                    case CommonFieldNameConstants.CREATE_NAME:
                    case CommonFieldNameConstants.UPDATE_NAME:
                        if (!Objects.isNull(user)) {
                            field.set(parameter, user.getUsername());
                        }

                        break;

                    case CommonFieldNameConstants.STATUS:
                        field.set(parameter, CommonDictEnum.Status.NORMAL.getValue());
                        break;

                    case CommonFieldNameConstants.IS_DELETED:
                        field.set(parameter, CommonDictEnum.IsDeleted.NO.getValue());
                        break;

                    default:
                }

                // 重新封装
                field.setAccessible(false);
            }

        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 检查属性是否需要填充
     *
     * @param field     属性
     * @param parameter 对象
     * @return {@link boolean}
     * @author gdk
     * @since 2022/8/14 16:48
     */
    public boolean needFill(Field field, Object parameter) throws IllegalAccessException {
        field.setAccessible(true);
        Object value = field.get(parameter);
        field.setAccessible(false);

        return StringUtils.isEmpty(value);
    }

    /**
     * 判断是否是vip
     *
     * @param vipExpire vip过期时间
     * @return {@link boolean}
     * @author gdk
     * @since 2023/5/27 20:45
     */
    public static boolean isVip(Date vipExpire) {
        long now = System.currentTimeMillis();
        return !Objects.isNull(vipExpire) && now < vipExpire.getTime();
    }
}
